package c2.group.business.tb.trial;

import c2.group.business.tb.TBGroupModule;
import cate.common.table.activity.throne.TBTrialChallengeRow;
import cate.common.table.d.GDThrone;
import cate.game.play.part.PlaySide;
import cate.game.pvp.throne.data.trial.TBTrialData;
import cate.game.pvp.throne.msg.*;
import com.fasterxml.jackson.annotation.JsonIgnore;
import easy.java.dev.note.NoteClass;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.annotation.Transient;

import java.util.ArrayList;
import java.util.concurrent.locks.ReentrantLock;

@NoteClass("王座争霸选拔赛")
@Slf4j
public class TBTrialModule extends TBGroupModule<TBTrialData> {

	@Override
	protected TBTrialData buildData() {
		return new TBTrialData();
	}

	@Override
	public void readFromBD() {
		for (TBTrialData data : useDb().tb.getTrial()) {
			data.init();
			groupMap.put(data.levelGroup, data);
		}
	}

	@Override
	public void save() {
		useDb().tb.saveTrial(new ArrayList<>(groupMap.values()));
	}

	@Override
	public void clear() {
		forGroups(TBTrialData::clear);
	}

	@Override
	public void onEnterNewSeason() {
		clear();
	}

	@Override
	public void onPeriodChange(byte period) {
		switch (period) {
			case GDThrone.Period.TRIAL:
				clear();
				break;
			case GDThrone.Period.KO:
				TBPartDataNotice notice = new TBPartDataNotice();
				forGroups(g -> notice.setTrial(g.levelGroup, g));
				parent.message.noticePart(notice);
				break;
			default:
				break;
		}
	}

	public TBTrialOpponentInnerResp getTrialOpponent(TBTrialOpponentReq req) {
		TBTrialOpponentInnerResp resp = new TBTrialOpponentInnerResp();
		if(!parent.getStatus().timeTable.inTrial()){
			return resp;
		}
		TBTrialChallengeRow row = context.table.throne.challenge.findRow(req.point);
		if (row != null) {
			for (Integer level : GDThrone.TrialLevel.ALL) {
				TBTrialChallengeRow.Range range = row.getRankRange(level);
				if (range != null) {
					PlaySide playSide = parent.rival.getGroup(req.group).randomPlaySide(req.roleUid, range.start, range.end);
					resp.addPlaySide(level, playSide);
				}
			}
		}
		return resp;
	}

	@JsonIgnore
	@Transient
	private ReentrantLock rankLock = new ReentrantLock();

	public void syncTrialRank(TBTrialRankSyncReq req) {
		if (!parent.getStatus().timeTable.inTrial()) {
			return;
		}
		try {
			rankLock.lock();
			boolean success = getGroup(req.levelGroup).record(req.playSide.snapshot.base, req.point);
			if (success) {
				parent.ps.setPlaySide(req.playSide);
			}
		} catch (Exception e) {
			log.error("", e);
		} finally {
			rankLock.unlock();
		}
	}

	public TBTrialInnerResp getTrialData(TBTrialInnerReq req) {
		return TBTrialInnerResp.of(getGroup(req.group));
	}

}
